#include "stdafx.h"
#include <fstream>
#include <sstream>

std::string HSItem::GetStatsString() const
{
	std::ostringstream oss;
	
	oss << sName << std::endl << std::endl;
	oss << "Level: " << uiLevel << std::endl;
	oss << "Value: " << uiValue << std::endl;
	oss << "Stack: " << uiStackSize;
	
	return oss.str();
}

std::string HSArmor::GetStatsString() const
{
	std::ostringstream oss;

	oss << sName << std::endl << std::endl;
	
	oss << "Physical Def.: " << fDefense + fDefenseBonus << std::endl;
	oss << "Fire Def.: " << fFireDef + fFireDefBonus << std::endl;
	oss << "Water Def.: " << fWaterDef + fWaterDefBonus << std::endl;
	oss << "Air Def.: " << fAirDef + fAirDefBonus << std::endl;
	oss << "Earth Def.: " << fEarthDef + fEarthDefBonus << std::endl;

	oss << "Level: " << uiLevel << std::endl;
	oss << "Value: " << uiValue;
	
	return oss.str();
}

std::string HSWeapon::GetStatsString() const
{
	std::ostringstream oss;
	
	oss << sName << std::endl << std::endl;

	oss << "Physical Atk.: " << fPhysAtk + fPhysAtkBonus << std::endl;
	oss << "Attack Power: " << fAtkPower + fAtkPowerBonus << std::endl;
	
	if ( bFireUnlocked )
	{
		oss << "Fire Atk.: " << fFireAtk + fFireAtkBonus << std::endl;
	}

	if ( bWaterUnlocked )
	{
		oss << "Water Atk.: " << fWaterAtk + fWaterAtkBonus << std::endl;
	}

	if ( bAirUnlocked )
	{
		oss << "Air Atk.: " << fAirAtk + fAirAtkBonus << std::endl;
	}

	if ( bEarthUnlocked )
	{
		oss << "Earth Atk.: " << fEarthAtk + fEarthAtkBonus << std::endl;
	}

	oss << "Level: " << uiLevel << std::endl;
	oss << "Value: " << uiValue;
	
	return oss.str();
}

HSInventory* HSInventory::sInv = NULL;

HSInventory::HSInventory()
{
	bActive = false;
	memset( pItems, 0, iCapacity * sizeof( HSItem* ) );

	pChest = NULL;
	pLegs = NULL;
	pHands = NULL;
	pFeet = NULL;
	pHead = NULL;
	pWeapon = NULL;

	iSelection = -1;

	aCanvas.SetColor( 0.1f, 0.1f, 0.1f, 1.0f );
	aCanvas.SetSize( HSSettings::fScrW, HSSettings::fScrH );
	aCanvas.SetPosition( HSSettings::fScrW / 2.0f, HSSettings::fScrH / 2.0f );

	float fPixel64 = MathUtil::PixelsToWorldUnits( 64.0f );

	aWeapon.SetPosition( 1.0f * fPixel64, 7.0f * fPixel64 );
	aWeapon.SetColor( 1.0f, 1.0f, 1.0f );
	aWeapon.SetSize( fPixel64, fPixel64 );
	aWeapon.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aHead.SetPosition( 2.0f * fPixel64, 8.0f * fPixel64 );
	aHead.SetColor( 1.0f, 1.0f, 1.0f );
	aHead.SetSize( fPixel64, fPixel64 );
	aHead.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aChest.SetPosition( 2.0f * fPixel64, 7.0f * fPixel64 );
	aChest.SetColor( 1.0f, 1.0f, 1.0f );
	aChest.SetSize( fPixel64, fPixel64 );
	aChest.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aLegs.SetPosition( 2.0f * fPixel64, 6.0f * fPixel64 );
	aLegs.SetColor( 1.0f, 1.0f, 1.0f );
	aLegs.SetSize( fPixel64, fPixel64 );
	aLegs.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aHands.SetPosition( 3.0f * fPixel64, 7.0f * fPixel64 );
	aHands.SetColor( 1.0f, 1.0f, 1.0f );
	aHands.SetSize( fPixel64, fPixel64 );
	aHands.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aFeet.SetPosition( 3.0f * fPixel64, 6.0f * fPixel64 );
	aFeet.SetColor( 1.0f, 1.0f, 1.0f );
	aFeet.SetSize( fPixel64, fPixel64 );
	aFeet.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aWeaponBkg.SetPosition( 1.0f * fPixel64, 7.0f * fPixel64 );
	aWeaponBkg.SetColor( 1.0f, 1.0f, 1.0f );
	aWeaponBkg.SetSize( fPixel64, fPixel64 );
	aWeaponBkg.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aHeadBkg.SetPosition( 2.0f * fPixel64, 8.0f * fPixel64 );
	aHeadBkg.SetColor( 1.0f, 1.0f, 1.0f );
	aHeadBkg.SetSize( fPixel64, fPixel64 );
	aHeadBkg.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aChestBkg.SetPosition( 2.0f * fPixel64, 7.0f * fPixel64 );
	aChestBkg.SetColor( 1.0f, 1.0f, 1.0f );
	aChestBkg.SetSize( fPixel64, fPixel64 );
	aChestBkg.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aLegsBkg.SetPosition( 2.0f * fPixel64, 6.0f * fPixel64 );
	aLegsBkg.SetColor( 1.0f, 1.0f, 1.0f );
	aLegsBkg.SetSize( fPixel64, fPixel64 );
	aLegsBkg.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aHandsBkg.SetPosition( 3.0f * fPixel64, 7.0f * fPixel64 );
	aHandsBkg.SetColor( 1.0f, 1.0f, 1.0f );
	aHandsBkg.SetSize( fPixel64, fPixel64 );
	aHandsBkg.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	aFeetBkg.SetPosition( 3.0f * fPixel64, 6.0f * fPixel64 );
	aFeetBkg.SetColor( 1.0f, 1.0f, 1.0f );
	aFeetBkg.SetSize( fPixel64, fPixel64 );
	aFeetBkg.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

	for ( unsigned int i = 0; i < 6; i++ )
	{
		for ( unsigned int j = 0; j < 8; j++ )
		{
			// 6 rows (i), 8 cols (j)
			aSlots[ (i * 8) + j ].SetPosition( (4.5f + (float)j) * fPixel64, (8.0f - (float)i) * fPixel64 );
			aSlots[ (i * 8) + j ].SetColor( 1.0f, 1.0f, 1.0f );
			aSlots[ (i * 8) + j ].SetSize( fPixel64, fPixel64 );
			aSlots[ (i * 8) + j ].SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );

			// 6 rows (i), 8 cols (j)
			aSlotsBkg[ (i * 8) + j ].SetPosition( (4.5f + (float)j) * fPixel64, (8.0f - (float)i) * fPixel64 );
			aSlotsBkg[ (i * 8) + j ].SetColor( 1.0f, 1.0f, 1.0f );
			aSlotsBkg[ (i * 8) + j ].SetSize( fPixel64, fPixel64 );
			aSlotsBkg[ (i * 8) + j ].SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );
		}
	}

	taStats.SetFont( "fontSmall" );
	taDesc.SetFont( "fontSmall" );
	taStats.SetPosition( 0.5f * fPixel64, 5.0f * fPixel64 );
	taDesc.SetPosition( 4.0f * fPixel64, 2.0f * fPixel64 );
	taStats.SetColor( 0.9f, 0.9f, 0.9f, 1.0f );
	taDesc.SetColor( 0.9f, 0.9f, 0.9f, 1.0f );
}

HSInventory& HSInventory::GetInstance()
{
	if ( !sInv )
	{
		sInv = new HSInventory();
	}

	return *sInv;
}

void HSInventory::MouseMotionEvent(Vec2i screenCoordinates)
{
	if ( !bActive )
	{
		return;
	}

	return;
}

void HSInventory::MouseDownEvent(Vec2i screenCoordinates, MouseButtonInput button)
{
	if ( !bActive )
	{
		return;
	}

	return;
}

int HSInventory::GetSelectedObject( Vec2i screenCoordinates )
{
	Vector2 wCoords = MathUtil::ScreenToWorld( screenCoordinates );

	if ( pWeapon && aWeapon.GetBoundingBox().Contains( wCoords ) )
	{
		return HSInventory::iWeapon;
	}

	if ( pHead && aHead.GetBoundingBox().Contains( wCoords ) )
	{
		return HSInventory::iHead;
	}

	if ( pChest && aChest.GetBoundingBox().Contains( wCoords ) )
	{
		return HSInventory::iChest;
	}

	if ( pLegs && aLegs.GetBoundingBox().Contains( wCoords ) )
	{
		return HSInventory::iLegs;
	}

	if ( pHands && aHands.GetBoundingBox().Contains( wCoords ) )
	{
		return HSInventory::iHands;
	}

	if ( pFeet && aFeet.GetBoundingBox().Contains( wCoords ) )
	{
		return HSInventory::iFeet;
	}

	for ( int i = 0; i < iCapacity; i++ )
	{
		if ( pItems[i] && aSlots[i].GetBoundingBox().Contains( wCoords ) )
		{
			return i;
		}
	}

	return -1;
}

int HSInventory::GetFreeSlot() const
{
	for ( int i = 0; i < iCapacity; i++ )
	{
		if ( !pItems[i] )
		{
			return i;
		}
	}

	return -1;
}

void HSInventory::EquipItem( const int iIndex )
{
	if ( iIndex < 0 || iIndex >= iCapacity )
	{
		return;
	}

	if ( pItems[iIndex]->sType == "weapon" )
	{
		HSItem* pSwap = pWeapon;
		pWeapon = pItems[iIndex];
		pItems[iIndex] = pSwap;
		UpdateTextures();
	}
	else if ( pItems[iIndex]->sType == "armor" )
	{
		HSArmor* pArmor = dynamic_cast<HSArmor*>( pItems[iIndex] );

		if ( !pArmor )
		{
			return;
		}

		if ( pArmor->sSubType == "head" )
		{
			HSItem* pSwap = pHead;
			pHead = pItems[iIndex];
			pItems[iIndex] = pSwap;
		}
		else if ( pArmor->sSubType == "chest" )
		{
			HSItem* pSwap = pChest;
			pChest = pItems[iIndex];
			pItems[iIndex] = pSwap;
		}
		else if ( pArmor->sSubType == "legs" )
		{
			HSItem* pSwap = pLegs;
			pLegs = pItems[iIndex];
			pItems[iIndex] = pSwap;
		}
		else if ( pArmor->sSubType == "hands" )
		{
			HSItem* pSwap = pHands;
			pHands = pItems[iIndex];
			pItems[iIndex] = pSwap;
		}
		else if ( pArmor->sSubType == "feet" )
		{
			HSItem* pSwap = pFeet;
			pFeet = pItems[iIndex];
			pItems[iIndex] = pSwap;
		}
		else
		{
			taDesc.SetDisplayString( "This item cannot be equipped!" );
			return;
		}

		UpdateTextures();
	}
	else
	{
		taDesc.SetDisplayString( "This item cannot be equipped!" );
	}
}

void HSInventory::DisplayItemInfo( const HSItem* pItem )
{
	if ( !pItem )
	{
		return;
	}

	if ( pItem->sType == "weapon" )
	{
		const HSWeapon* pWeapon = dynamic_cast<const HSWeapon*>( pItem );

		if ( !pWeapon )
		{
			return;
		}

		taStats.SetDisplayString( pWeapon->GetStatsString() );
		taDesc.SetDisplayString( pWeapon->sDesc );
	}
	else if ( pItem->sType == "armor" )
	{
		const HSArmor* pArmor = dynamic_cast<const HSArmor*>( pItem );

		if ( !pArmor )
		{
			return;
		}

		taStats.SetDisplayString( pArmor->GetStatsString() );
		taDesc.SetDisplayString( pArmor->sDesc );
	}
	else
	{
		taStats.SetDisplayString( pItem->GetStatsString() );
		taDesc.SetDisplayString( pItem->sDesc );
	}
}

void HSInventory::MouseUpEvent(Vec2i screenCoordinates, MouseButtonInput button)
{
	if ( !bActive )
	{
		return;
	}

	if ( button == MOUSE_LEFT )
	{
		iSelection = GetSelectedObject( screenCoordinates );
		
		if ( iSelection >= 0 )
		{
			switch ( iSelection )
			{
			case HSInventory::iWeapon:
				DisplayItemInfo( pWeapon );
				break;
			case HSInventory::iHead:
				DisplayItemInfo( pHead );
				break;
			case HSInventory::iChest:
				DisplayItemInfo( pChest );
				break;
			case HSInventory::iLegs:
				DisplayItemInfo( pLegs );
				break;
			case HSInventory::iHands:
				DisplayItemInfo( pHands );
				break;
			case HSInventory::iFeet:
				DisplayItemInfo( pFeet );
				break;
			default:
				DisplayItemInfo( pItems[iSelection] );
				break;
			}
		}

		UpdateSelection();
		return;
	}

	if ( button == MOUSE_RIGHT )
	{
		int iActionSelection = GetSelectedObject( screenCoordinates );
		
		if ( iSelection >= 0 && iSelection == iActionSelection )
		{
			int iFreeSlot = GetFreeSlot();

			switch ( iSelection )
			{
			case HSInventory::iWeapon:
				if ( pWeapon )
				{
					if ( iFreeSlot >= 0 && iFreeSlot < iCapacity )
					{
						pItems[iFreeSlot] = pWeapon;
						pWeapon = NULL;
						UpdateTextures();
					}
					else
					{
						taDesc.SetDisplayString( "Cannot unequip weapon, you have full inventory!" );
					}
				}
				break;
			case HSInventory::iHead:
				if ( pHead )
				{
					if ( iFreeSlot >= 0 && iFreeSlot < iCapacity )
					{
						pItems[iFreeSlot] = pHead;
						pHead = NULL;
						UpdateTextures();
					}
					else
					{
						taDesc.SetDisplayString( "Cannot unequip headgear, you have full inventory!" );
					}
				}
				break;
			case HSInventory::iChest:
				if ( pChest )
				{
					if ( iFreeSlot >= 0 && iFreeSlot < iCapacity )
					{
						pItems[iFreeSlot] = pChest;
						pChest = NULL;
						UpdateTextures();
					}
					else
					{
						taDesc.SetDisplayString( "Cannot unequip armor, you have full inventory!" );
					}
				}
				break;
			case HSInventory::iLegs:
				if ( pLegs )
				{
					if ( iFreeSlot >= 0 && iFreeSlot < iCapacity )
					{
						pItems[iFreeSlot] = pLegs;
						pLegs = NULL;
						UpdateTextures();
					}
					else
					{
						taDesc.SetDisplayString( "Cannot unequip pants, you have full inventory!" );
					}
				}
				break;
			case HSInventory::iHands:
				if ( pHands )
				{
					if ( iFreeSlot >= 0 && iFreeSlot < iCapacity )
					{
						pItems[iFreeSlot] = pHands;
						pHands = NULL;
						UpdateTextures();
					}
					else
					{
						taDesc.SetDisplayString( "Cannot unequip gloves, you have full inventory!" );
					}
				}
				break;
			case HSInventory::iFeet:
				if ( pFeet )
				{
					if ( iFreeSlot >= 0 && iFreeSlot < iCapacity )
					{
						pItems[iFreeSlot] = pFeet;
						pFeet = NULL;
						UpdateTextures();
					}
					else
					{
						taDesc.SetDisplayString( "Cannot unequip boots, you have full inventory!" );
					}
				}
				break;
			default:
				if ( pItems[iSelection] )
				{
					// TODO: perform the action of the item
					if ( pItems[iSelection]->sAction == "equip" )
					{
						EquipItem( iSelection );
					}
				}
				break;
			}
		}

		return;
	}

	if ( button == MOUSE_WHEELED )
	{
		Deactivate();
		thePlayer.Activate();
		theLevel.Activate();
		return;
	}
}

void HSInventory::MouseWheelEvent(const Vector2 &scrollOffset)
{
	if ( !bActive )
	{
		return;
	}

	return;
}

bool HSInventory::HasItem( const std::string& sId )
{
	for ( int i = 0; i < iCapacity; i++ )
	{
		if ( pItems[i] )
		{
			if ( pItems[i]->sId == sId )
			{
				return true;
			}
		}
	}

	return false;
}

bool HSInventory::AddItem( const std::string& sId )
{
	const HSItem* pAddItem = HSInventory::GetItem( sId );

	if ( !pAddItem )
	{
		return false;
	}

	for ( int i = 0; i < iCapacity; i++ )
	{
		if ( !pItems[i] )
		{
			if ( pAddItem->sType == "weapon" )
			{
				const HSWeapon* pWeapon = dynamic_cast<const HSWeapon*>( pAddItem );

				if ( !pWeapon )
				{
					return false;
				}

				pItems[i] = new HSWeapon();

				if ( !pItems[i] )
				{
					return false;
				}

				*(HSWeapon*)pItems[i] = *pWeapon;
				UpdateTextures();
				return true;
			}
			else if ( pAddItem->sType == "armor" )
			{
				const HSArmor* pArmor = dynamic_cast<const HSArmor*>( pAddItem );

				if ( !pArmor )
				{
					return false;
				}

				pItems[i] = new HSArmor();

				if ( !pItems[i] )
				{
					return false;
				}

				*(HSArmor*)pItems[i] = *pArmor;
				UpdateTextures();
				return true;
			}
			else if ( pAddItem->sType == "item" )
			{
				const HSItem* pItem = dynamic_cast<const HSItem*>( pAddItem );

				if ( !pItem )
				{
					return false;
				}

				pItems[i] = new HSItem();

				if ( !pItems[i] )
				{
					return false;
				}

				*pItems[i] = *pItem;
				UpdateTextures();
				return true;
			}
			
			// if we get here something went wrong
			return false;
		}
	}

	return false;
}

void HSInventory::UpdateTextures()
{
	for ( int i = 0; i < iCapacity; i++ )
	{
		if ( pItems[i] )
		{
			aSlots[i].SetSprite( "Resources/Images/" + pItems[i]->sTex, 0, GL_CLAMP, GL_LINEAR, false );
		}
		else
		{
			aSlots[i].SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );
		}
	}

	if ( pWeapon )
	{
		aWeapon.SetSprite( "Resources/Images/" + pWeapon->sTex, 0, GL_CLAMP, GL_LINEAR, false );
	}
	else
	{
		aWeapon.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );
	}

	if ( pHead )
	{
		aHead.SetSprite( "Resources/Images/" + pHead->sTex, 0, GL_CLAMP, GL_LINEAR, false );
	}
	else
	{
		aHead.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );
	}

	if ( pChest )
	{
		aChest.SetSprite( "Resources/Images/" + pChest->sTex, 0, GL_CLAMP, GL_LINEAR, false );
	}
	else
	{
		aChest.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );
	}

	if ( pLegs )
	{
		aLegs.SetSprite( "Resources/Images/" + pLegs->sTex, 0, GL_CLAMP, GL_LINEAR, false );
	}
	else
	{
		aLegs.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );
	}

	if ( pHands )
	{
		aHands.SetSprite( "Resources/Images/" + pHands->sTex, 0, GL_CLAMP, GL_LINEAR, false );
	}
	else
	{
		aHands.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );
	}

	if ( pFeet )
	{
		aFeet.SetSprite( "Resources/Images/" + pFeet->sTex, 0, GL_CLAMP, GL_LINEAR, false );
	}
	else
	{
		aFeet.SetSprite( "Resources/Images/inv_bkg.png", 0, GL_CLAMP, GL_LINEAR, false );
	}
}

void HSInventory::UpdateSelection()
{
	// selection color: 0 153 255 -> 0.0 0.6 1.0
	static Color whiteColor = Color( 1.0f, 1.0f, 1.0f );
	static Color selectColor = Color( 0.0f, 0.6f, 1.0f );

	aWeaponBkg.SetColor( whiteColor );
	aHeadBkg.SetColor( whiteColor );
	aChestBkg.SetColor( whiteColor );
	aLegsBkg.SetColor( whiteColor );
	aHandsBkg.SetColor( whiteColor );
	aFeetBkg.SetColor( whiteColor );

	for ( int i = 0; i < iCapacity; i++ )
	{
		if ( i == iSelection )
		{
			aSlotsBkg[i].SetColor( selectColor );
		}
		else
		{
			aSlotsBkg[i].SetColor( whiteColor );
		}
	}

	if ( iSelection < 0 )
	{
		taDesc.SetDisplayString( "" );
		taStats.SetDisplayString( "" );
		return;
	}

	switch ( iSelection )
	{
	case HSInventory::iWeapon:
		aWeaponBkg.SetColor( selectColor );
		break;
	case HSInventory::iHead:
		aHeadBkg.SetColor( selectColor );
		break;
	case HSInventory::iChest:
		aChestBkg.SetColor( selectColor );
		break;
	case HSInventory::iLegs:
		aLegsBkg.SetColor( selectColor );
		break;
	case HSInventory::iHands:
		aHandsBkg.SetColor( selectColor );
		break;
	case HSInventory::iFeet:
		aFeetBkg.SetColor( selectColor );
		break;
	}
}

void HSInventory::Activate()
{
	if ( bActive )
	{
		return;
	}

	iSelection = -1;
	theWorld.Add( &aCanvas, iCanvasLayer );

	theWorld.Add( &aChestBkg, iBackgroundLayer );
	theWorld.Add( &aLegsBkg, iBackgroundLayer );
	theWorld.Add( &aHandsBkg, iBackgroundLayer );
	theWorld.Add( &aFeetBkg, iBackgroundLayer );
	theWorld.Add( &aHeadBkg, iBackgroundLayer );
	theWorld.Add( &aWeaponBkg, iBackgroundLayer );

	theWorld.Add( &aChest, iItemsLayer );
	theWorld.Add( &aLegs, iItemsLayer );
	theWorld.Add( &aHands, iItemsLayer );
	theWorld.Add( &aFeet, iItemsLayer );
	theWorld.Add( &aHead, iItemsLayer );
	theWorld.Add( &aWeapon, iItemsLayer );

	for ( int i = 0; i < iCapacity; i++ )
	{
		theWorld.Add( &aSlotsBkg[ i ], iBackgroundLayer );
		theWorld.Add( &aSlots[ i ], iItemsLayer );
	}

	taStats.SetDisplayString( "Item stats" );
	taDesc.SetDisplayString( "This is your inventory" );

	theWorld.Add( &taStats, iTextLayer );
	theWorld.Add( &taDesc, iTextLayer );

	UpdateTextures();
	UpdateSelection();

	bActive = true;
	theCamera.Reset();
	theCamera.SetPosition( HSSettings::fScrW / 2.0f, HSSettings::fScrH / 2.0f );
}

void HSInventory::Deactivate()
{
	if ( !bActive )
	{
		return;
	}

	theWorld.Remove( &aCanvas );

	theWorld.Remove( &aChestBkg );
	theWorld.Remove( &aLegsBkg );
	theWorld.Remove( &aHandsBkg );
	theWorld.Remove( &aFeetBkg );
	theWorld.Remove( &aHeadBkg );
	theWorld.Remove( &aWeaponBkg );

	theWorld.Remove( &aChest );
	theWorld.Remove( &aLegs );
	theWorld.Remove( &aHands );
	theWorld.Remove( &aFeet );
	theWorld.Remove( &aHead );
	theWorld.Remove( &aWeapon );

	for ( int i = 0; i < iCapacity; i++ )
	{
		theWorld.Remove( &aSlotsBkg[ i ] );
		theWorld.Remove( &aSlots[ i ] );
	}

	theWorld.Remove( &taStats );
	theWorld.Remove( &taDesc );

	bActive = false;
}

HSInventory::HSItemMap HSInventory::smapItems;

const HSItem* HSInventory::GetItem( const std::string& sId )
{
	HSItemMap::const_iterator it = smapItems.find( sId );

	if ( it != smapItems.end() )
	{
		return it->second;
	}

	return NULL;
}

bool HSInventory::LoadItems( const std::string& sItemDefs )
{
	std::ifstream in( "Resources/Data/" + sItemDefs, std::ifstream::in );

	if ( !in.is_open() )
	{
		sysLog.Printf( "Failed to open %s", sItemDefs.c_str() );
		return false;
	}
	
	while ( !in.eof() )
	{
		if ( in.fail() )
		{
			sysLog.Printf( "Failed to parse data from %s", sItemDefs.c_str() );
			return false;
		}

		std::string sKeyword, sId, sName, sType, sTex, sDesc, sAct, sStackable;
		unsigned int uiLevel, uiValue, uiStackSize;

		in >> sKeyword >> uiLevel >> sId >> sName >> sType >> sTex >> sDesc >> sAct >> uiValue >> sStackable >> uiStackSize;

		std::replace( sName.begin(), sName.end(), '_', ' ');
		std::replace( sDesc.begin(), sDesc.end(), '_', ' ');

		if ( in.fail() )
		{
			sysLog.Printf( "Failed to parse data from %s", sItemDefs.c_str() );
			return false;
		}

		if ( smapItems.find( sId ) != smapItems.end() )
		{
			sysLog.Printf( "Item '%s' already defined", sId.c_str() );
			return false;
		}

		if ( sKeyword == "weapon" )
		{
			std::string sSubType, sFireUnlocked, sWaterUnlocked, sAirUnlocked, sEarthUnlocked;
			float fPhysAtk, fPhysAtkBonus, fAtkPower, fAtkPowerBonus;
			float fFireAtk, fWaterAtk, fAirAtk, fEarthAtk;
			float fFireAtkBonus, fWaterAtkBonus, fAirAtkBonus, fEarthAtkBonus;

			in >> sSubType >> fPhysAtk >> fPhysAtkBonus >> fAtkPower >> fAtkPowerBonus;
			in >> sFireUnlocked >> sWaterUnlocked >> sAirUnlocked >> sEarthUnlocked;
			in >> fFireAtk >> fWaterAtk >> fAirAtk >> fEarthAtk;
			in >> fFireAtkBonus >> fWaterAtkBonus >> fAirAtkBonus >> fEarthAtkBonus;

			if ( in.fail() )
			{
				sysLog.Printf( "Failed to parse data from %s", sItemDefs.c_str() );
				return false;
			}

			HSWeapon* pNewItem = new HSWeapon();
			pNewItem->sId = sId;
			pNewItem->sName = sName;
			pNewItem->sType = sType;
			pNewItem->sTex = sTex;
			pNewItem->sDesc = sDesc;
			pNewItem->sAction = sAct;
			pNewItem->bStackable = ( sStackable == "yes" );
			pNewItem->uiLevel = uiLevel;
			pNewItem->uiValue = uiValue;
			pNewItem->uiStackSize = uiStackSize;

			pNewItem->sSubType = sSubType;
			pNewItem->fPhysAtk = fPhysAtk;
			pNewItem->fPhysAtkBonus = fPhysAtkBonus;
			pNewItem->fAtkPower = fAtkPower;
			pNewItem->fAtkPowerBonus = fAtkPowerBonus;

			pNewItem->bFireUnlocked = ( sFireUnlocked == "yes" );
			pNewItem->bWaterUnlocked = ( sWaterUnlocked == "yes" );
			pNewItem->bAirUnlocked = ( sAirUnlocked == "yes" );
			pNewItem->bEarthUnlocked = ( sEarthUnlocked == "yes" );

			pNewItem->fFireAtk = fFireAtk;
			pNewItem->fWaterAtk = fWaterAtk;
			pNewItem->fAirAtk = fAirAtk;
			pNewItem->fEarthAtk = fEarthAtk;

			pNewItem->fFireAtkBonus = fFireAtkBonus;
			pNewItem->fWaterAtkBonus = fWaterAtkBonus;
			pNewItem->fAirAtkBonus = fAirAtkBonus;
			pNewItem->fEarthAtkBonus = fEarthAtkBonus;	

			smapItems[ sId ] = pNewItem;
		}
		else if ( sKeyword == "armor" )
		{
			std::string sSubType;
			float fDefense, fFireDef, fWaterDef, fAirDef, fEarthDef;
			float fDefenseBonus, fFireDefBonus, fWaterDefBonus, fAirDefBonus, fEarthDefBonus;

			in >> sSubType >> fDefense >> fDefenseBonus;
			in >> fFireDef >> fWaterDef >> fAirDef >> fEarthDef;
			in >> fFireDefBonus >> fWaterDefBonus >> fAirDefBonus >> fEarthDefBonus;

			if ( in.fail() )
			{
				sysLog.Printf( "Failed to parse data from %s", sItemDefs.c_str() );
				return false;
			}

			HSArmor* pNewItem = new HSArmor();
			pNewItem->sId = sId;
			pNewItem->sName = sName;
			pNewItem->sType = sType;
			pNewItem->sTex = sTex;
			pNewItem->sDesc = sDesc;
			pNewItem->sAction = sAct;
			pNewItem->bStackable = ( sStackable == "yes" );
			pNewItem->uiLevel = uiLevel;
			pNewItem->uiValue = uiValue;
			pNewItem->uiStackSize = uiStackSize;

			pNewItem->sSubType = sSubType;
			pNewItem->fDefense = fDefense;
			pNewItem->fDefenseBonus = fDefenseBonus;

			pNewItem->fFireDef = fFireDef;
			pNewItem->fWaterDef = fWaterDef;
			pNewItem->fAirDef = fAirDef;
			pNewItem->fEarthDef = fEarthDef;

			pNewItem->fFireDefBonus = fFireDefBonus;
			pNewItem->fWaterDefBonus = fWaterDefBonus;
			pNewItem->fAirDefBonus = fAirDefBonus;
			pNewItem->fEarthDefBonus = fEarthDefBonus;	

			smapItems[ sId ] = pNewItem;
		}
		else if ( sKeyword == "item" )
		{
			HSItem* pNewItem = new HSItem();
			pNewItem->sId = sId;
			pNewItem->sName = sName;
			pNewItem->sType = sType;
			pNewItem->sTex = sTex;
			pNewItem->sDesc = sDesc;
			pNewItem->sAction = sAct;
			pNewItem->bStackable = ( sStackable == "yes" );
			pNewItem->uiLevel = uiLevel;
			pNewItem->uiValue = uiValue;
			pNewItem->uiStackSize = uiStackSize;

			smapItems[ sId ] = pNewItem;
		}
		else
		{
			sysLog.Printf( "Unrecognized keyword '%s'", sKeyword.c_str() );
			return false;
		}
	}

	return true;
}
